﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using ProjectResistance.Shell.Entities;
using OpenNETCF.IoC;
using OpenNETCF;
using System.Windows.Forms;

namespace ProjectResistance.Shell.Controllers
{
    internal class ResistorController
    {
        public event EventHandler<GenericEventArgs<decimal>> ResistanceChanged;
        public event EventHandler<GenericEventArgs<ToleranceValues>> ToleranceChanged;
        public event EventHandler<GenericEventArgs<int>> SelectedBandChanged;

        private Resistor Resistor { get; set; }
        private ToleranceValues[] ToleranceList { get; set; }

        public bool TouchMode { get; set; }
        public int SelectedBand { get; private set; }

        internal ResistorController()
        {
            ToleranceList = (from t in Enum2.GetValues(typeof(ToleranceValues))
                             orderby t
                             select (ToleranceValues)t).ToArray();

            Resistor = new Resistor();
            Resistor.ResistanceChanged += new EventHandler<OpenNETCF.IoC.GenericEventArgs<decimal>>(Resistor_ResistanceChanged);
            Resistor.ToleranceChanged += new EventHandler<GenericEventArgs<ToleranceValues>>(Resistor_ToleranceChanged);

            // initialize band slection to #1 (for non-touch devices)
            SelectedBand = 1;

            // set this to false for non-touch devices
            TouchMode = CurrentDevice.HasTouchScreen;
        }

        [EventSubscription(EventNames.DPadEvent, ThreadOption.Caller)]
        public void DPadHandler(object sender, KeyEventArgs e)
        {
            // if we're in touch mode, simply turn it off
            if (TouchMode)
            {
                TouchMode = false;
                RaiseSelectedBandChanged(SelectedBand);
                return;
            }

            // TODO: handle D-Pad events
            switch(e.KeyCode)
            {
                case Keys.Right:
                    if(++SelectedBand > 4)
                    {
                        SelectedBand = 1;
                    }
                    RaiseSelectedBandChanged(SelectedBand);
                    break;
                case Keys.Left:
                    if (--SelectedBand < 1)
                    {
                        SelectedBand = 4;
                    }
                    RaiseSelectedBandChanged(SelectedBand);
                    break;
                case Keys.Up:
                    if (SelectedBand < 4)
                    {
                        ResistanceUp(SelectedBand);
                    }
                    else
                    {
                        ToleranceUp();
                    }
                    break;
                case Keys.Down:
                    if (SelectedBand < 4)
                    {
                        ResistanceDown(SelectedBand);
                    }
                    else
                    {
                        ToleranceDown();
                    }
                    break;
            }

        }

        private void RaiseSelectedBandChanged(int band)
        {
            EventHandler<GenericEventArgs<int>> handler = SelectedBandChanged;
            if (handler == null) return;

            handler(this, new GenericEventArgs<int>(band));
        }

        private void Resistor_ToleranceChanged(object sender, GenericEventArgs<ToleranceValues> e)
        {
            EventHandler<GenericEventArgs<ToleranceValues>> handler = ToleranceChanged;
            if (handler == null) return;

            ToleranceChanged(this, e);
        }

        private void Resistor_ResistanceChanged(object sender, OpenNETCF.IoC.GenericEventArgs<decimal> e)
        {
            EventHandler<GenericEventArgs<decimal>> handler = ResistanceChanged;
            if(handler == null) return;

            ResistanceChanged(this, e);
        }

        public void SetResistance(decimal resistance)
        {
            Resistor.Resistance = resistance;
        }

        public void SetTolerance(ToleranceValues tolerance)
        {
            Resistor.Tolerance = tolerance;
        }

        public ToleranceValues GetTolerance()
        {
            return Resistor.Tolerance;
        }

        public decimal GetResistance()
        {
            return Resistor.Resistance;
        }

        public void ToleranceUp()
        {
            ToleranceValues current = Resistor.Tolerance;
            if (current == ToleranceList.Last())
            {
                Resistor.Tolerance = ToleranceList.First();
            }
            else
            {
                Resistor.Tolerance = ToleranceList.First(t => (int)t > (int)current); 
            }
        }

        public void ToleranceDown()
        {
            ToleranceValues current = Resistor.Tolerance;
            if (current == ToleranceList.First())
            {
                Resistor.Tolerance = ToleranceList.Last();
            }
            else
            {
                Resistor.Tolerance = ToleranceList.Last(t => (int)t < (int)current);
            }
        }

        public void ResistanceUp(int digit)
        {
            if ((digit <= 0) || (digit > 3)) throw new ArgumentOutOfRangeException();

            Resistor.Resistance = Utility.ResistanceUp(Resistor.Resistance, digit);
        }

        public void ResistanceDown(int digit)
        {
            if ((digit <= 0) || (digit > 3)) throw new ArgumentOutOfRangeException();

            Resistor.Resistance = Utility.ResistanceDown(Resistor.Resistance, digit);
        }
    }
}
